#pragma ident "$Id: CSDetectorLC.hpp 2648 2011-06-09 08:01:41Z shjzhang $"

/**
 * @file CSDetectorLC.hpp
 * General Solver.
 */

#ifndef GPSTK_CSDetectorLC_HPP
#define GPSTK_CSDetectorLC_HPP

//============================================================================
//
//  Revision
//
//  2019/08/13  
//  make a generic PPP solver for multiple-gnss data.  
//
//  2020/01/16 
//  modify the variable-class to replace the old ambiguity class  
//
//  shjzhang    
//
//============================================================================


#include "SolverBase.hpp"
#include "TypeID.hpp"
#include "ProcessingClass.hpp"
#include "EquationSystem.hpp"
#include "StochasticModel.hpp"
#include "SimpleKalmanFilter.hpp"
#include "SolverMWAR.hpp"


namespace gpstk
{

   ///////////////////////////////////////////////////////////////////
   // warning:
   // some solution realted data structures are defined in SolverBase
   // In the DIA method,
   // if the apriori variance is known, the Z-Test wil be used.
   ///////////////////////////////////////////////////////////////////

   struct DeltaX
   {
       DeltaX()
           : dx(0.0), dy(0.0), dz(0.0), dt(0.0)
       {}

       double dx, dy, dz, dt;
   };

   class CSDetectorLC : public SolverBase, public ProcessingClass
   {
   public:

      CSDetectorLC()
          : firstTime(true), 
            applyDXConstr(false), 
            applyDTConstr(false), 
            threshold(0.05),
            useDIA(true),
            ZTest(true),
            globalTest(true),
            sigDX(1.0), sigDY(1.0), sigDZ(1.0), sigDT(1.0), 
            pCSStream(NULL), pSolStream(NULL)
      {
          gpsCombTypeSet.clear();
          galCombTypeSet.clear();
          bdsCombTypeSet.clear();
          gloCombTypeSet.clear();

          usingGPS = true;
          usingGAL = false;
          usingBDS = false;
          usingGLO = false;

          gpsCombTypeSet.insert(TypeID::LC12);

          Init();
      }


         /** Returns a reference to a gnnsRinex object after solving
          *  the previously defined equation system.
          *
          * @param gData    Data object holding the data.
          */
      virtual gnssRinex& Process(gnssRinex& gData )
         noexcept(false);


      virtual void getEpochDiffData(gnssRinex& gData )
         noexcept(false);
      
         /** Measurement Update of the kalman filter.
          *
          * @param gData    Data object holding the data.
          */
      virtual int DIA( int numApriori,
                       Vector<double>& xhatminus,
                       Matrix<double>& Pminus,
                       Vector<double>& prefitResiduals,
                       Matrix<double>& designMatrix,
                       Matrix<double>& weightMatrix,
                       Vector<double>& postfitResiduals,
                       Vector<double>& standResidual,
                       double&         sig,
                       Vector<int>&    outlierVector)
         noexcept(false);

      virtual int Robust(  int numApriori,
                           Vector<double>& xhatminus,
                           Matrix<double>& Pminus,
                           Vector<double>& prefitResiduals,
                           Matrix<double>& designMatrix,
                           Matrix<double>& weightMatrix,
                           Vector<double>& postfitResiduals,
                           Vector<double>& standResidual,
                           double&         sig,
                           Vector<int>&    outlierVector)
         noexcept(false);

      virtual int Robust(  Vector<double>& prefitResiduals,
                           Matrix<double>& designMatrix,
                           Matrix<double>& weightMatrix,
                           Vector<double>& postfitResiduals,
                           Vector<double>& standResidual,
                           double&         sig,
                           Vector<int>&    outlierVector)
         noexcept(false);

      virtual int getMaxIndex( Vector<double>& residual,
                               Vector<int>& flagVec);

      virtual int getMinIndex( Vector<double>& residual,
                               Vector<int>& flagVec);

      virtual CSDetectorLC& addType(const TypeID& type, const SatID::SatelliteSystem& sys)
      {
          if(sys==SatelliteSystem::GPS)
          {
              usingGPS = true;
              gpsCombTypeSet.insert(type);
          }
          else if(sys==SatelliteSystem::Galileo)
          {
              usingGAL = true;
              galCombTypeSet.insert(type);
          }
          else if(sys==SatelliteSystem::BDS)
          {
              usingBDS = true;
              bdsCombTypeSet.insert(type);
          }
          else if(sys==SatelliteSystem::GLONASS)
          {
              usingGLO = true;
              gloCombTypeSet.insert(type);
          }
          return (*this);
      };

      virtual void setThreshold(double value)
      {
          threshold = value;
      };

      virtual void setUseDIA(bool use)
      {
          useDIA = use;
      };

         /// Returns an index identifying this object.
      virtual void setUpEquations(void) ;

      virtual Variable getVariable( const TypeID& type,
                                    const VariableSet& varSet) const
         noexcept(false);

      virtual void setCSDataStream(std::ofstream& stream)
      {
          pCSStream = &stream;
      };

      virtual void setCSSolStream(std::ofstream& stream)
      {
          pSolStream = &stream;
      };

      virtual void setAprioriDX(double sig)
      {
          sigDX = sig;
          sigDY = sig;
          sigDZ = sig;
          applyDXConstr = true;
      };

      virtual void setAprioriDT(double sig)
      {
          sigDT = sig;
          applyDTConstr = true;
      };


         /// Returns an index identifying this object.
      virtual void Init(void) ;

      DeltaX getDeltaX()
      {
          return deltax;
      };

         /// Returns an index identifying this object.
      virtual int getIndex(void) const;

         /// Returns a string identifying this object.
      virtual std::string getClassName(void) const;

         /// Destructor.
      virtual ~CSDetectorLC() {};

   private:

      bool useDIA;
      bool ZTest;

      DeltaX deltax;

      bool firstTime;
      bool globalTest;

      bool applyDXConstr;
      bool applyDTConstr;

      bool usingGPS, usingGAL, usingBDS, usingGLO;

      double sigDX, sigDY, sigDZ, sigDT;

      double threshold;

      TypeIDSet gpsCombTypeSet, galCombTypeSet, bdsCombTypeSet, gloCombTypeSet;

      VariableSet currentUnkSet;

         /// Geometry matrix
      Matrix<double> hMatrix;

         /// Weights matrix
      Matrix<double> rMatrix;

         /// Measurements vector (Prefit-residuals)
      Vector<double> measVector;

      Vector<double> solution;
      Matrix<double> covMatrix;

      double vtpvAcc;
      int numObsAcc;

      satTypeValueMap stvDataPrev;

         /// Equation system
      EquationSystem  equSystem;

      std::ofstream* pCSStream;
      std::ofstream* pSolStream;

         /// Initial index assigned to this class.
      static int classIndex;

         /// Index belonging to this object.
      int index;

         /// Sets the index and increment classIndex.
      void setIndex(void)
      { index = classIndex++; };


   }; // End of class 'CSDetectorLC'


      //@}

}  // End of namespace gpstk
#endif   // GPSTK_CSDetectorLC_HPP
